package com.sky.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sky.context.BaseContext;
import com.sky.dto.*;
import com.sky.entity.*;
import com.sky.constant.MessageConstant;
import com.sky.exception.BusinessException;
import com.sky.exception.OrderBusinessException;
import com.sky.mapper.OrderDetailMapper;
import com.sky.mapper.UserMapper;
import com.sky.result.PageResult;
import com.sky.result.Result;
import com.sky.service.AddressBookService;
import com.sky.service.OrderDetailService;
import com.sky.service.OrdersService;
import com.sky.mapper.OrdersMapper;
import com.sky.service.ShoppingCartService;
import com.sky.vo.*;

import com.sky.websocket.WebSocKetService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;

import com.sky.utils.WeChatPayUtil;
/**
 * @author 86158
 * @description 针对表【orders(订单表)】的数据库操作Service实现
 * @createDate 2025-08-25 21:22:35
 */
@Service
public class OrdersServiceImpl extends ServiceImpl<OrdersMapper, Orders>
        implements OrdersService {
    @Autowired
    private AddressBookService addressBookService;
    @Autowired
    private OrdersMapper ordersMapper;
    @Autowired
    private OrderDetailService orderDetailService;
    @Autowired
    private OrderDetailMapper orderDetailMapper;
    @Autowired
    private ShoppingCartService shoppingCartService;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private WeChatPayUtil weChatPayUtil;
    @Autowired
    private WebSocKetService webSocKetService;

    @Override
    public OrderSubmitVO submit(OrdersSubmitDTO ordersSubmitDTO) {
        //判段地址是否为空！
        AddressBook addressBook = addressBookService.getById(ordersSubmitDTO.getAddressBookId());
        if (addressBook == null) {
            throw new RuntimeException(MessageConstant.ADDRESS_BOOK_IS_NULL);
        }
        //判段购物车是否为空
        LambdaQueryWrapper<ShoppingCart> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ShoppingCart::getUserId, BaseContext.getCurrentId());
        List<ShoppingCart> carts = shoppingCartService.list(queryWrapper);
        if (carts == null || carts.size() == 0) {
            throw new RuntimeException(MessageConstant.SHOPPING_CART_IS_NULL);
        }
        //向订单表中插入一条数据(n对个商品为一条数据)
        //1.创建按订单对象
        Orders orders = new Orders();
        BeanUtils.copyProperties(ordersSubmitDTO,orders);
        //订单好为线程
        orders.setNumber(String.valueOf(System.currentTimeMillis()));//订单号
        orders.setUserId(BaseContext.getCurrentId());//用户id
        orders.setOrderTime(LocalDateTime.now());//下单时间
        orders.setPayStatus(Orders.UN_PAID);
        orders.setStatus(Orders.PENDING_PAYMENT);//待支付
        orders.setPayMethod(ordersSubmitDTO.getPayMethod());//支付方式
        orders.setPhone(addressBook.getPhone());//手机号
        orders.setAddress(addressBook.getDetail());//地址
        orders.setConsignee(addressBook.getConsignee());//收货人
        ordersMapper.insert(orders);
        //向订单消息表中添加n对个订单详情数据
        //根据购物车中的数量创建订单详情数据
        List<OrderDetail> orderDetails = new ArrayList<>();
        for (ShoppingCart cart : carts) {
            OrderDetail orderDetail = new OrderDetail();
            BeanUtils.copyProperties(cart, orderDetail);
            orderDetail.setOrderId(orders.getId());//订单id
            orderDetails.add(orderDetail);
        }
        orderDetailService.saveBatch(orderDetails);

        //下单成功清空购物车！
        shoppingCartService.remove(queryWrapper);
        //封装对象
        return new OrderSubmitVO(orders.getId(), orders.getNumber(),orders.getAmount(),orders.getOrderTime());
    }

    /**
     * 订单支付
     *
     * @param ordersPaymentDTO
     * @return
     */
    public OrderPaymentVO payment(OrdersPaymentDTO ordersPaymentDTO) throws Exception {
        // 当前登录用户id
        Long userId = BaseContext.getCurrentId();

        // 使用MyBatis-Plus的selectById查询用户
        User user = userMapper.selectById(userId);

        // 调用微信支付接口，生成预支付交易单
        JSONObject jsonObject = weChatPayUtil.pay(
                ordersPaymentDTO.getOrderNumber(), // 商户订单号
                new BigDecimal(0.01), // 支付金额，单位 元
                "苍穹外卖订单", // 商品描述
                user.getOpenid() // 微信用户的openid
        );

        if (jsonObject.getString("code") != null && jsonObject.getString("code").equals("ORDERPAID")) {
            throw new OrderBusinessException("该订单已支付");

        }

        OrderPaymentVO vo = jsonObject.toJavaObject(OrderPaymentVO.class);
        vo.setPackageStr(jsonObject.getString("package"));

        return vo;
    }

    /**
     * 支付成功，修改订单状态
     *
     * @param outTradeNo
     */
    public void paySuccess(String outTradeNo) {
        // 使用MyBatis-Plus的LambdaQueryWrapper构建查询条件
        LambdaQueryWrapper<Orders> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Orders::getNumber, outTradeNo);

        // 根据订单号查询订单
        Orders ordersDB = ordersMapper.selectOne(queryWrapper);

        // 构建更新对象
        Orders orders = Orders.builder()
                .id(ordersDB.getId())
                .status(Orders.TO_BE_CONFIRMED)
                .payStatus(Orders.PAID)
                .checkoutTime(LocalDateTime.now())
                .build();

        // 使用MyBatis-Plus的updateById更新订单
        ordersMapper.updateById(orders);
        //向客户端推送消息，数据包括type:订单类型1为来单提醒2.客户催单，ordersid:订单号，content:提示信息
        //封装数据
        Map map = new HashMap();
        map.put("type", 1);
        map.put("orderId", ordersDB.getId());
        map.put("content", "订单号：" + outTradeNo);
        //将Map转化为字符串
        String json = JSON.toJSONString(map);
        System.out.println(json);
        webSocKetService.sendToAllClient(json);

    }

    @Override
    public Result reminder(Long id) {
        //根据id查询订单
        Orders orders = ordersMapper.selectById(id);
        if (orders == null) {
            return Result.error("订单不存在");
        }
        //给客户端推送消息
        Map map = new HashMap();
        map.put("type", 2);
        map.put("orderId", orders.getId());
        map.put("content", "订单号：" + orders.getNumber());
        String json = JSON.toJSONString(map);
        webSocKetService.sendToAllClient(json);
        return Result.success(json);

    }
    /**
     * 根据id取消订单
     * */

    @Override
    public void cancel(OrdersRejectionDTO ordersRejectionDTO) {
        Long orderId = ordersRejectionDTO.getId();
        Orders orders = ordersMapper.selectById(orderId);
        if (orders == null) {
            throw new RuntimeException("订单不存在");
        }
        if (orders.getStatus() != Orders.PENDING_PAYMENT) {
            throw new RuntimeException("订单不能取消");
        }
        orders.setStatus(Orders.CANCELLED);
        orders.setCancelReason(ordersRejectionDTO.getRejectionReason());
    }

    @Override
    public OrderOverViewVO countStatus() {
        //获取当前时间
        LocalDateTime now = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);//获取当前时间的00：00：00
        LocalDateTime last = LocalDateTime.of(LocalDate.now(), LocalTime.MAX);//获取当前时间的23：59：59
        //统计当天的待派送的订单
        Integer ordersCount = getOrdersCount(now, last, Orders.DELIVERY_IN_PROGRESS);
        //统计待接单的订单
        Integer waitingOrderCount = getOrdersCount(now, last, Orders.TO_BE_CONFIRMED);
        //统计已完成的订单
        Integer completedOrderCount = getOrdersCount(now, last, Orders.COMPLETED);
        //统计已取消的订单
        Integer cancelledOrderCount = getOrdersCount(now, last, Orders.CANCELLED);
        //统计总订单数
        Integer allOrderCount = getOrdersCount(now, last, null);
        return OrderOverViewVO.builder()
                .waitingOrders(waitingOrderCount)
                .deliveredOrders(ordersCount)
                .completedOrders(completedOrderCount)
                .cancelledOrders(cancelledOrderCount)
                .allOrders(allOrderCount)
                .build();
    }
    /**
     * 确认订单
     * */

    @Override
    public void complete(Long id) {
        LambdaUpdateWrapper<Orders> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(Orders::getId, id);
        updateWrapper.set(Orders::getStatus, Orders.COMPLETED);
        this.update(updateWrapper);
    }

    /**
     * 拒绝订单
     * */

    @Override
    public void rejection(OrdersRejectionDTO ordersRejectionDTO) {
        Long orderId = ordersRejectionDTO.getId();
        Orders orders = ordersMapper.selectById(orderId);
        if (orders == null) {
            throw new RuntimeException("订单不存在");
        }
        orders.setStatus(Orders.CANCELLED);
        orders.setCancelReason(ordersRejectionDTO.getRejectionReason());
        ordersMapper.updateById(orders);

    }
    /**
     * 接单
     * */

    @Override
    public void confirm(Long id) {
        LambdaUpdateWrapper<Orders> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(Orders::getId, id);
        updateWrapper.set(Orders::getStatus, Orders.CONFIRMED);
        this.update(updateWrapper);

    }

    @Override
    public OrderVO getOrderDetailsById(Long id) {
        // 1. 查主表
        Orders order = ordersMapper.selectById(id);
        if (order == null) throw new BusinessException("订单不存在");

        // 2. 查明细
        List<OrderDetail> details = orderDetailMapper.selectList(
                new LambdaQueryWrapper<OrderDetail>().eq(OrderDetail::getOrderId, id)
        );

        // 3. 计算：菜品总数量、菜品小计
        int totalCount = 0;
        BigDecimal itemsSubtotal = BigDecimal.ZERO;

        List<OrderDetail> detailVOs = new ArrayList<>();
        for (OrderDetail d : details) {
            int qty = d.getNumber() == null ? 0 : d.getNumber();
            totalCount += qty;

            BigDecimal unitPrice = d.getAmount();                        // 若 amount 是单价（常见）
            BigDecimal subtotal = unitPrice.multiply(BigDecimal.valueOf(qty));
            // 若 amount 是小计，则：
            // BigDecimal subtotal = d.getAmount();
            // BigDecimal unitPrice = subtotal.divide(BigDecimal.valueOf(qty), 2, RoundingMode.HALF_UP);

            itemsSubtotal = itemsSubtotal.add(subtotal);

            OrderDetailVO vo = new OrderDetailVO();
            vo.setId(d.getId());
            vo.setOrderId(d.getOrderId());
            vo.setDishId(d.getDishId());
            vo.setSetmealId(d.getSetmealId());
            vo.setName(d.getName());
            vo.setImage(d.getImage());
            vo.setDishFlavor(d.getDishFlavor());
            vo.setNumber(qty);
            vo.setUnitPrice(unitPrice);
            vo.setSubtotal(subtotal);
            detailVOs.add(vo);
        }

        // 4. 配送费/打包费/总金额
        BigDecimal deliveryFee = BigDecimal.valueOf(6);                  // 固定6元
        BigDecimal packFee = BigDecimal.valueOf(totalCount);             // 打包费=菜品总数量（元）
        BigDecimal totalAmount = itemsSubtotal.add(deliveryFee).add(packFee);

        // 5. 组装返回
        OrderVO vo = new OrderVO();
        BeanUtils.copyProperties(order, vo);
        vo.setOrderDetailList(detailVOs);
        vo.setDeliveryFee(deliveryFee);
        vo.setItemsSubtotal(itemsSubtotal);
        vo.setPackAmount(totalCount);                                    // 保持你实体里 packAmount 为 int
        vo.setAmount(totalAmount);                                       // 返回总金额

        return vo;
    }

    @Override
    public IPage<Orders> listOredsers(IPage<Orders> page1, OrdersPageQueryDTO ordersPageQueryDTO) {
        return ordersMapper.listOredsers(page1, ordersPageQueryDTO);
    }

    @Override
    public void delivery(Long id) {
        LambdaUpdateWrapper<Orders> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(Orders::getId, id);
        updateWrapper.set(Orders::getStatus, Orders.DELIVERY_IN_PROGRESS);
        this.update(updateWrapper);
    }
    /**
     * 重复订单
     * */

    @Override
    public void repetition(Long id) {
        Orders orders = ordersMapper.selectById(id);
        if (orders == null) {
            throw new RuntimeException("订单不存在");
        }
        if (orders.getStatus() != Orders.CONFIRMED) {
            throw new RuntimeException("订单状态异常");
        }
        orders.setStatus(Orders.TO_BE_CONFIRMED);
        ordersMapper.updateById(orders);

    }
    /**
     * 取消订单
     * */

    @Override
    public void cancelorder(Long id) {
        Orders orders = ordersMapper.selectById(id);
        if (orders == null) {
            throw new RuntimeException("订单不存在");
        }
        if (orders.getStatus() != Orders.CONFIRMED) {
            throw new RuntimeException("订单状态异常");
        }
        orders.setStatus(Orders.CANCELLED);
        ordersMapper.updateById(orders);

    }

    /**
     * 用户端订单分页查询
     *
     * @param pageNum
     * @param pageSize
     * @param status
     * @return
     */
    public PageResult pageQuery4User(int pageNum, int pageSize, Integer status) {
        // 创建分页对象
        Page<Orders> page = new Page<>(pageNum, pageSize);

        // 构建查询条件
        QueryWrapper<Orders> queryWrapper = new QueryWrapper<>();
        // 设置用户ID条件
        queryWrapper.eq("user_id", BaseContext.getCurrentId());
        // 设置状态条件（如果不为null）
        if (status != null) {
            queryWrapper.eq("status", status);
        }
        // 按订单时间降序排序
        queryWrapper.orderByDesc("order_time");

        // 执行分页查询
        IPage<Orders> ordersPage = ordersMapper.selectPage(page, queryWrapper);

        List<OrderVO> list = new ArrayList<>();

        // 查询出订单明细，并封装入OrderVO进行响应
        if (ordersPage.getTotal() > 0) {
            for (Orders orders : ordersPage.getRecords()) {
                Long orderId = orders.getId();// 订单id

                // 查询订单明细（这里也可以考虑使用MyBatis-Plus的查询）
                List<OrderDetail> orderDetails = orderDetailMapper.selectList(
                        new LambdaQueryWrapper<OrderDetail>().eq(OrderDetail::getOrderId, orderId)
                );

                OrderVO orderVO = new OrderVO();
                BeanUtils.copyProperties(orders, orderVO);
                orderVO.setOrderDetailList(orderDetails);

                list.add(orderVO);
            }
        }

        return new PageResult(ordersPage.getTotal(), list);
    }





    /**
     * 统计指定时间区间的订单数量
     * */
    public Integer getOrdersCount(LocalDateTime beginTime, LocalDateTime endTime, Integer status) {
        Map map = new HashMap();
        map.put("begin",beginTime);
        map.put("end", endTime);
        map.put("status", status);
        return ordersMapper.getOrdersCount(map);

    }


}




